﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using MobilnyDostawca;
using MobilnyDostawca.Enums;
using MobilnyDostawca.Repositories;
using MobilnyDostawca.ViewModels;

namespace MobilnyDostawca.Controllers
{
    [Authorize]
    public class DelivererController : Controller
    {
        //
        // GET: /Deliverer/
        public ViewResult Index()
        {
            return View(LoadDostawcyIndexViewModel(Repository.GetAllDeliverers()));
        }

        //
        // GET: /Deliverer/Details/5
        public ViewResult Details(int id)
        {
            return View(LoadDostawcyDetailsViewModel(Repository.GetDelivererByID(id)));
        }
        
        //
        // GET: /Deliverer/Edit/5
        public ActionResult Edit(int id)
        {
            return View(LoadDostawcaEditViewModel(Repository.GetPossibleToAddSubregionsForDeliverer(id), id));
        }

        //
        // POST: /Deliverer/Edit/5
        [HttpPost]
        public ActionResult Edit(DostawcyEditViewModel dostawcyEditViewModel)
        {
            if (ModelState.IsValid)
            {
                Repository.UpdateSubregionDeliverer(dostawcyEditViewModel.ID, dostawcyEditViewModel.Subregion);
                return RedirectToAction("Index");
            }
            return View(LoadDostawcaEditViewModel(Repository.GetPossibleToAddSubregionsForDeliverer(dostawcyEditViewModel.ID), dostawcyEditViewModel.ID));
        }

        private IEnumerable<DostawcyIndexViewModel> LoadDostawcyIndexViewModel(IEnumerable<Dostawcy> dostawcy)
        {
            List<DostawcyIndexViewModel> dostawcyList = new List<DostawcyIndexViewModel>();

            foreach (var dostawca in dostawcy)
            {
                DostawcyIndexViewModel dostawcaTmp = new DostawcyIndexViewModel();
                dostawcaTmp.ID = dostawca.ID;
                dostawcaTmp.Imie = dostawca.Imie;
                dostawcaTmp.Nazwisko = dostawca.Nazwisko;
                dostawcaTmp.Telefon = dostawca.Telefon;
                dostawcaTmp.Region = dostawca.Subregiony.Count > 0 ? dostawca.Subregiony.FirstOrDefault().Regiony.Nazwa : "";
                dostawcaTmp.Subregiony.AddRange(Repository.GetSubregionsForDeliverer(dostawcaTmp.ID));
                dostawcaTmp.Przesylki.AddRange(Repository.GetActualParcelsForDeliverer(dostawcaTmp.ID));
                dostawcyList.Add(dostawcaTmp);
            }
            return dostawcyList;
        }

        private DostawcyDetailsViewModel LoadDostawcyDetailsViewModel(Dostawcy dostawca)
        {
            DostawcyDetailsViewModel dostawcaTmp = new DostawcyDetailsViewModel();

            dostawcaTmp.ID = dostawca.ID;
            dostawcaTmp.Imie = dostawca.Imie;
            dostawcaTmp.Nazwisko = dostawca.Nazwisko;
            dostawcaTmp.Telefon = dostawca.Telefon;
            dostawcaTmp.Region = dostawca.Subregiony.Count > 0 ? dostawca.Subregiony.FirstOrDefault().Regiony.Nazwa : "";
            dostawcaTmp.Subregiony.AddRange(Repository.GetSubregionsForDeliverer(dostawcaTmp.ID));

            List<Przesylki> przesylkiTmp = new List<Przesylki>();
            przesylkiTmp.AddRange(Repository.GetAllDelivererParcelsWithoutHistorical(dostawcaTmp.ID));
            dostawcaTmp.PrzesylkiWszystkie.AddRange(CompleteInformationAboutDeliverer(przesylkiTmp, dostawcaTmp.Subregiony));
            dostawcaTmp.PrzesylkiAktualne.AddRange(CompleteInformationAboutDeliverer(Repository.GetActualParcelsForDeliverer(dostawcaTmp.ID), dostawcaTmp.Subregiony));
            UpdateParcelsListsForDelivererDetails(dostawcaTmp);

            return dostawcaTmp;
        }

        private IEnumerable<PrzesylkiForDostawcyDetailsViewModel> CompleteInformationAboutDeliverer(IEnumerable<Przesylki> przesylki, IEnumerable<Subregiony> subregiony) 
        {
            List<PrzesylkiForDostawcyDetailsViewModel> przesylkiLst = new List<PrzesylkiForDostawcyDetailsViewModel>();
            foreach (var item in przesylki) 
            {
                PrzesylkiForDostawcyDetailsViewModel przesylkaTmp = new PrzesylkiForDostawcyDetailsViewModel();
                przesylkaTmp.ID = item.ID;
                przesylkaTmp.Status = item.Statusy.Nazwa;
                przesylkaTmp.Info = BuildInfo(item, subregiony);
                przesylkiLst.Add(przesylkaTmp);
            }
            return przesylkiLst;
        }

        private string BuildInfo(Przesylki przesylka, IEnumerable<Subregiony> subregiony)
        {
            StringBuilder infoSB = new StringBuilder();
            Dictionary<DeliveryDirection, string> communicatesDictionary = new Dictionary<DeliveryDirection, string>();

            FillDeliveryDirectionDictionary(przesylka, communicatesDictionary);

            if (przesylka.Klienci.Subregion == przesylka.Klienci1.Subregion)
            {
                // n -> o
                infoSB.Append(communicatesDictionary[DeliveryDirection.ndo]);
            }
            else
            {
                if (przesylka.Klienci.Subregiony.Region == przesylka.Klienci1.Subregiony.Region)
                {
                    if (przesylka.Klienci.Subregiony.Dostawca == przesylka.Klienci1.Subregiony.Dostawca)
                    {
                        // n -> o
                        infoSB.Append(communicatesDictionary[DeliveryDirection.ndo]);
                    }
                    else
                    {
                        foreach (var subregion in subregiony)
                        {
                            if (przesylka.Klienci.Subregion == subregion.ID)
                            {
                                // n -> m
                                infoSB.Append(communicatesDictionary[DeliveryDirection.ndm]);
                                break;
                            }
                            else if (przesylka.Klienci1.Subregion == subregion.ID)
                            {
                                // m -> o
                                infoSB.Append(communicatesDictionary[DeliveryDirection.mdo]);
                                break;
                            }
                        }
                    }
                }
                else 
                {
                    if (przesylka.Klienci.Subregiony.Region == subregiony.First().Region)
                    {
                        // n -> m
                        infoSB.Append(communicatesDictionary[DeliveryDirection.ndm]);
                    }
                    else 
                    { 
                        // m -> o
                        infoSB.Append(communicatesDictionary[DeliveryDirection.mdo]);
                    }
                }
            }
            return infoSB.ToString();
        }

        private static void FillDeliveryDirectionDictionary(Przesylki przesylka, Dictionary<DeliveryDirection, string> communicates)
        {
            string magazynDlaNadawcy = przesylka.Klienci.Subregiony.Regiony.Magazyny.Single(m => m.Nazwa.Contains(przesylka.Klienci.Subregiony.Nazwa)).Nazwa;
            string magazynDlaOdbiorcy = przesylka.Klienci1.Subregiony.Regiony.Magazyny.Single(m => m.Nazwa.Contains(przesylka.Klienci1.Subregiony.Nazwa)).Nazwa;
            communicates.Add(DeliveryDirection.ndo, string.Format("<div><p>Odebrać od <b>{0} {1}</b>, <b>{2}</b>, <b>({3})</b> i dostarczyć do <b>{4} {5}</b>, <b>{6}</b>, <b>({7})</b></p><div>",
                przesylka.Klienci.Imie, przesylka.Klienci.Nazwisko, przesylka.Klienci.Adres, przesylka.Klienci.Subregiony.Nazwa,
                przesylka.Klienci1.Imie, przesylka.Klienci1.Nazwisko, przesylka.Klienci1.Adres, przesylka.Klienci1.Subregiony.Nazwa));
            communicates.Add(DeliveryDirection.ndm, string.Format("<div><p>Odebrać od <b>{0} {1}</b>, <b>{2}</b>, <b>({3})</b> i dostarczyć do <b>{4}</b></p><div>",
                przesylka.Klienci.Imie, przesylka.Klienci.Nazwisko, przesylka.Klienci.Adres, przesylka.Klienci.Subregiony.Nazwa, magazynDlaNadawcy));
            communicates.Add(DeliveryDirection.mdo, string.Format("<div><p>Odebrać z <b>{0}</b> i dostarczyć do <b>{1} {2}</b>, <b>{3}</b>, <b>({4})</b></p><div>",
                magazynDlaOdbiorcy, przesylka.Klienci1.Imie, przesylka.Klienci1.Nazwisko, przesylka.Klienci1.Adres, przesylka.Klienci1.Subregiony.Nazwa));
        }

        public DostawcyEditViewModel LoadDostawcaEditViewModel(IEnumerable<Subregiony> subregiony, int id) 
        {
            DostawcyEditViewModel model = new DostawcyEditViewModel();
            model.ID = id;
            if (Repository.IsDelivererWithoutSubregion(id))
            {
                model.Region = string.Empty;
                foreach (var sub in subregiony)
                {
                    model.Subregiony.Add(new SelectListItem() { Text = string.Format("{0} ({1})", sub.Nazwa, sub.Regiony.Nazwa), Value = sub.ID.ToString() });
                }
            }
            else 
            {
                model.Region = subregiony.First().Regiony.Nazwa;
                foreach (var sub in subregiony)
                {
                    model.Subregiony.Add(new SelectListItem() { Text = sub.Nazwa, Value = sub.ID.ToString() });
                }
            }

            return model;
        }

        private void UpdateParcelsListsForDelivererDetails(DostawcyDetailsViewModel dostawca) 
        {
            List<PrzesylkiForDostawcyDetailsViewModel> temp = new List<PrzesylkiForDostawcyDetailsViewModel>();
            temp.AddRange(dostawca.PrzesylkiAktualne);

            foreach (var item in dostawca.PrzesylkiWszystkie)
            {
                if (!dostawca.PrzesylkiAktualne.Any(p => p.ID == item.ID))
                {
                    temp.Add(item);
                }
            }
            dostawca.PrzesylkiWszystkie.Clear();
            dostawca.PrzesylkiWszystkie.AddRange(temp);
        }
    }
}